<template>
  <div>
    <input ref="refFile" type="file" style="display: none" @change="uploadFile">
    <!--  提示  -->
    <el-dialog
      v-model="statusShow"
      :title="fileInfo.fileName"
      :show-close="false"
      width="500px">
      <el-progress :text-inside="true" :stroke-width="24" :percentage="schedule" status="success"></el-progress>
      <template #footer>
      <span class="dialog-footer">
        <el-button type="primary" @click="closeDialog">确定</el-button>
      </span>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import {reactive, getCurrentInstance, ref} from 'vue'
import SparkMD5 from 'spark-md5'
import {ElMessage} from "element-plus";
import {chunkUploadForMinio, chunkUploadToMinio, composeFileForMinio} from '@/api/system.js'
import axios from 'axios';
import request from '@/utils/request'

export default {
  name: "upload",
  setup(props, {emit}) {
    const fileInfo = reactive({
      fileName: '',
      fileMd5: '',
      chunkCount: 0
    })
    const {proxy} = getCurrentInstance();
    const statusShow = ref(false)
    const schedule = ref(0)
    const refFile = ref(null);
    // 分片大小 5mb
    const _unitM = 5
    const chunkSize = ref(_unitM * 1024 * 1024)

    const uploadFile = async () => {
      statusShow.value = false;

      // 获取用户选择的文件
      const file = refFile.value.files[0]

      if (file === undefined) {
        ElMessage.error('文件损坏请重新上传')
        return
      }

      if (file.size > 0) {
        fileInfo.fileName = file.name
        fileInfo.chunkCount = Math.ceil(file.size / chunkSize.value)
        fileInfo.fileMd5 = await getFileMd5(file)
        schedule.value = 0;
      }
      console.log(fileInfo)
      const _limitCount = 100
      if (fileInfo.chunkCount > _limitCount) {
        ElMessage.error('文件大于' + _limitCount * _unitM + "M，不允许上传")
        return
      }
      statusShow.value = true

      chunkUploadForMinio(fileInfo).then(async (res) => {
          // 分片上传完成 待合并文件
          if (res.uploadCode === 3) {
            const res = await composeFileForMinio(fileInfo);
            emit('success', {fileName: file.name, fileSize: file.size, url: res.fileUrl});
            closeDialog();
            return
          }

          if (res.uploadCode === 1) {
            schedule.value = 100
            emit('success', {fileName: file.name, fileSize: file.size, url: res.fileUrl});
            closeDialog();
            return
          }

          const chunkUploadUrls = res.chunkUploadUrls

          for (const item of chunkUploadUrls) {
            // 分片开始位置
            const start = (item.partNumber - 1) * chunkSize.value
            // 分片结束位置
            const end = Math.min(file.size, start + chunkSize.value)
            // 取文件指定范围内的byte，从而得到分片数据
            const chunkFile = file.slice(start, end)
            await chunkUploadToMinio(item.uploadUrl, chunkFile, item.contentType)
            schedule.value = parseFloat((item.partNumber / fileInfo.chunkCount * 100).toString().substring(0, 4))
          }

          const res1 = await composeFileForMinio(fileInfo);
          emit('success', {fileName: file.name, fileSize: file.size, url: res1.fileUrl});
          closeDialog();
        }
      )
    }
    const getFileMd5 = (file) => {
      const fileReader = new FileReader()
      fileReader.readAsBinaryString(file)
      const spark = new SparkMD5()
      return new Promise((resolve) => {
        fileReader.onload = (e) => {
          spark.appendBinary(e.target.result)
          resolve(spark.end())
        }
      })
    }

    const composeFile = (fileInfo) => {
      return composeFileForMinio(fileInfo);
    }

    const selectFile = () => {
      refFile.value.click();
    }

    const closeDialog = () => {
      statusShow.value = false;
      schedule.value = 0;
    }

    return {
      fileInfo,
      schedule,
      statusShow,
      chunkSize,
      refFile,
      uploadFile,
      selectFile,
      closeDialog
    }
  }
}
</script>

<style scoped>
</style>
